using MinoChat.Ui.Behaviors;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Documents;
using System.Windows.Media;

namespace MinoChat.Ui.Controls;
//本质不是控件，而是一个附加属性，使用时在ScrollViewer上设置该附加属性以及样式就行
// 为ScrollViewer提供固定大小滑块的附加属性
// xmlns:miniui="clr-namespace:MinoChat.Ui.Controls;assembly=MinoChat.Ui"
//<ScrollViewer Padding = "{TemplateBinding Padding}"
//   miniui:ThumbScrollBar.EnableFixedThumb="True"
//   Style="{StaticResource ThumbScrollViewer}">
//</ScrollViewer>
public static class ThumbScrollBar
{
    /// <summary>
    /// 附加属性：是否启用固定大小的滑块（默认为 true）
    /// </summary>
    public static readonly DependencyProperty EnableFixedThumbProperty =
        DependencyProperty.RegisterAttached(
            "EnableFixedThumb",
            typeof(bool),
            typeof(ThumbScrollBar),
            new PropertyMetadata(true, OnEnableFixedThumbChanged));

    public static bool GetEnableFixedThumb(DependencyObject obj)
    {
        return (bool)obj.GetValue(EnableFixedThumbProperty);
    }

    public static void SetEnableFixedThumb(DependencyObject obj, bool value)
    {
        obj.SetValue(EnableFixedThumbProperty, value);
    }

    private static void OnEnableFixedThumbChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (!(bool)e.NewValue)
            return;

        if (d is ScrollViewer scrollViewer)
        {
            // 等待ScrollViewer完全加载后再附加Adorner
            scrollViewer.Loaded += (s, args) => AttachAdornerToScrollViewer(scrollViewer);
        }
        else if (d is ScrollBar scrollBar)
        {
            // 直接在ScrollBar上设置附加属性
            scrollBar.Loaded += (s, args) => AttachAdornerToScrollBar(scrollBar);
        }
    }

    private static void AttachAdornerToScrollViewer(ScrollViewer scrollViewer)
    {
        // 查找垂直滚动条
        var scrollBar = FindVisualChild<ScrollBar>(scrollViewer, sb => sb.Orientation == Orientation.Vertical);
        if (scrollBar != null)
        {
            AttachAdornerToScrollBar(scrollBar);
        }
    }

    private static void AttachAdornerToScrollBar(ScrollBar scrollBar)
    {
        // 查找ScrollBar内部的Thumb
        var thumb = FindVisualChild<Thumb>(scrollBar);
        if (thumb != null)
        {
            // 尝试获取AdornerLayer，使用多层级查找策略
            var adornerLayer = GetAdornerLayerSafe(scrollBar);
            if (adornerLayer != null)
            {
                // 创建并添加装饰器
                var adorner = new ScrollBarThumbAdorner(thumb, scrollBar);
                adornerLayer.Add(adorner);

                // 监听滚动条值变化，更新装饰器
                scrollBar.ValueChanged += (s, e) => adorner.InvalidateVisual();

                // 监听滑块的鼠标事件，更新装饰器
                thumb.MouseEnter += (s, e) => adorner.InvalidateVisual();
                thumb.MouseLeave += (s, e) => adorner.InvalidateVisual();

                // 拖动时强制显示
                thumb.DragStarted += (s, e) =>
                {
                    scrollBar.Opacity = 1.0;
                    adorner.InvalidateVisual();
                };

                thumb.DragDelta += (s, e) => adorner.InvalidateVisual();
                thumb.DragCompleted += (s, e) => adorner.InvalidateVisual();

                // 监听滚动条透明度变化，更新装饰器
                var opacityDescriptor = System.ComponentModel.DependencyPropertyDescriptor.FromProperty(
                    UIElement.OpacityProperty, typeof(ScrollBar));
                opacityDescriptor?.AddValueChanged(scrollBar, (s, e) => adorner.InvalidateVisual());
            }
            else
            {
                // 如果无法获取AdornerLayer（例如在FlowDocument中），回退到传统样式
                // 修改Thumb的样式为可见的固定大小滑块
                ApplyFallbackThumbStyle(thumb);
            }
        }
    }

    /// <summary>
    /// 安全地获取AdornerLayer，支持多层级向上查找
    /// </summary>
    private static AdornerLayer? GetAdornerLayerSafe(Visual element)
    {
        // 首先尝试直接获取
        var adornerLayer = AdornerLayer.GetAdornerLayer(element);
        if (adornerLayer != null)
            return adornerLayer;

        // 向上遍历视觉树查找AdornerLayer
        DependencyObject? current = element;
        while (current != null)
        {
            current = VisualTreeHelper.GetParent(current);
            if (current is Visual visualParent)
            {
                adornerLayer = AdornerLayer.GetAdornerLayer(visualParent);
                if (adornerLayer != null)
                    return adornerLayer;
            }
        }

        return null;
    }

    /// <summary>
    /// 应用回退样式：当无法使用装饰器时，使用传统的可见滑块
    /// </summary>
    private static void ApplyFallbackThumbStyle(Thumb thumb)
    {
        thumb.Height = 40;
        thumb.Width = 7;

        var border = new System.Windows.Controls.Border
        {
            Background = new SolidColorBrush(Color.FromRgb(0x88, 0x88, 0x88)),
            CornerRadius = new CornerRadius(3.5),
            Width = 7,
            Height = 40
        };

        // 创建控件模板
        var template = new ControlTemplate(typeof(Thumb));
        var factory = new FrameworkElementFactory(typeof(System.Windows.Controls.Border));
        factory.SetValue(System.Windows.Controls.Border.BackgroundProperty, new SolidColorBrush(Color.FromRgb(0x88, 0x88, 0x88)));
        factory.SetValue(System.Windows.Controls.Border.CornerRadiusProperty, new CornerRadius(3.5));
        factory.SetValue(FrameworkElement.WidthProperty, 7.0);
        factory.SetValue(FrameworkElement.HeightProperty, 40.0);

        template.VisualTree = factory;
        thumb.Template = template;
    }

    // 辅助方法：查找可视树中的子元素
    private static T? FindVisualChild<T>(DependencyObject? parent, Predicate<T>? predicate = null) where T : DependencyObject
    {
        if (parent == null) return null;

        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
        {
            var child = VisualTreeHelper.GetChild(parent, i);
            if (child is T typedChild && (predicate == null || predicate(typedChild)))
            {
                return typedChild;
            }

            var result = FindVisualChild<T>(child, predicate);
            if (result != null)
            {
                return result;
            }
        }

        return null;
    }
}